package com.wilschrader.demarche;

import java.util.Collections;
import java.util.EnumSet;

/**
 * Fleets are broken up into an offensive and defensive fleet.
 * 
 * @author Wil Schrader
 * @modifications
 * 	08172011	Now uses the new UnitContainer superclass.
 * 	08112011	Init revision.
 * 
 */
public class Fleet extends UnitContainer {
	
	public static enum Type {
		Defensive,
		Attacking
	}
	
	private String name;
	private int hitCounter = 0;

	/**
	 * Fleets are required to be named for battle statistics purposes.
	 * Damage models dictate how damage is applied to a fleet.
	 * 
	 * @param name
	 */
	public Fleet(String name) {
		Simulation.debugOutput("Created Fleet (" + name+ ").");
		this.name = name;
	}
	
	/**
	 * As a stage or round of combat takes place, hits are registered to a fleet that are later allocated.\
	 * 
	 * @param hits The number of hits to be additively registered to be later allocated
	 */
	public void registerHits(int hits) {
		hitCounter += hits;
	}

	/**
	 * Allocate the hits at the end of a stage or round of combat that have been
	 * registered.
	 * 
	 * @param types The types of units that should have damage allocated to.
	 * @return		True if all hits allocated, false if there are no more units to allocate damage to.
	 */
	public boolean allocateHits(EnumSet<Unit.Type> types) {
		
		if (activeUnits.size() == 0)
			return false;
		
		out: while (hitCounter > 0 && activeUnits.size() > 0) {
			
			if (activeUnits.size() == 0)
				return false;
			
			Collections.sort(activeUnits);

			for (Unit unit : activeUnits) {
				if (types.contains(unit.getType())) {
					if (unit.damage()) {
						Simulation.debugOutput("Unit (" + unit.getClass().getSimpleName() + ") from Fleet (" + getName() + ") has been destroyed.");
						destroyUnit(unit);
					} else {
						Simulation.debugOutput("Unit (" + unit.getClass().getSimpleName() + ") from Fleet (" + getName() + ") has sustained damage.");
					}

					hitCounter--;
					
					/*
					 * Damaged or destroyed a unit, no need to continue to loop through all of the units.
					 * The continue statement is used to avoid the next few lines...
					 */
					continue out;
				}
			}
			
			/*
			 * ... because if this is ever hit, we know we have looped through the entire list
			 * of units without damaging a unit, meaning there are no more units that can take damage.
			 */
			hitCounter = 0;
			return false;
		}
	
		return true;
	}
	
	public void allocateHits(Unit.Type type) {
		allocateHits(EnumSet.of(type));
	}
	
	public String getName() {
		return name;
	}
}
